using System;
using System.Collections.Generic;
using System.Linq;
using Dapper;
using MediatR;
using Microsoft.Extensions.Logging;
using RBAC.Domain.Dto.Output;
using RBAC.Domain.WarehouseManagement;
using RBAC.ErrorCode;
using RBAC.Interstructrue.Base;
using RBAC.Read.Api.Application.Command.ERP.PurchasingManagement.PurchaseInvoicefolder;

namespace RBAC.Read.Api.Application.Handler.ERP.PurchasingManagement.PurchaseInvoicefolder
{
    /// <summary>
    /// 采购发票明细表（联查发票+供应商+物料）- 行分页
    /// </summary>
    public class GetPurchaseInvoiceDetailsCommandHandler : IRequestHandler<GetPurchaseInvoiceDetailsCommands, APIPaging<PurchaseInvoiceDetailRowDto>>
    {
        private readonly ILogger<GetPurchaseInvoiceDetailsCommandHandler> _logger;
        private readonly IBaseRepository<PurchaseInvoice> _invoiceRepository;

        public GetPurchaseInvoiceDetailsCommandHandler(
            ILogger<GetPurchaseInvoiceDetailsCommandHandler> logger,
            IBaseRepository<PurchaseInvoice> invoiceRepository)
        {
            _logger = logger;
            _invoiceRepository = invoiceRepository;
        }

        public Task<APIPaging<PurchaseInvoiceDetailRowDto>> Handle(GetPurchaseInvoiceDetailsCommands request, CancellationToken cancellationToken)
        {
            var res = new APIPaging<PurchaseInvoiceDetailRowDto>();
            try
            {
                var whereParts = new List<string> { "pi.IsDeleted = 0" };
                var param = new DynamicParameters();

                if (!string.IsNullOrWhiteSpace(request.DocumentCode))
                {
                    whereParts.Add("pi.DocumentCode LIKE @DocumentCode");
                    param.Add("DocumentCode", $"%{request.DocumentCode}%");
                }
                if (!string.IsNullOrWhiteSpace(request.SupplierName))
                {
                    // 兼容供应商别名/简称，以及历史上 pi.SupplierId 可能存放名称的情况
                    whereParts.Add(@"(
                        s.Supplier_Name LIKE @SupplierName OR s.Supplier_Alias LIKE @SupplierName OR s.Short_Name LIKE @SupplierName
                        OR pi.SupplierId LIKE @SupplierName
                    )");
                    param.Add("SupplierName", $"%{request.SupplierName}%");
                }
                if (request.InvoiceDateStart.HasValue)
                {
                    whereParts.Add("pi.InvoiceDate >= @InvoiceDateStart");
                    param.Add("InvoiceDateStart", request.InvoiceDateStart.Value);
                }
                if (request.InvoiceDateEnd.HasValue)
                {
                    whereParts.Add("pi.InvoiceDate <= @InvoiceDateEnd");
                    param.Add("InvoiceDateEnd", request.InvoiceDateEnd.Value);
                }
                // 明细表需求暂不提供发票号/税号/物料编码名称筛选，如需请在 Commands 中补充后再加入过滤

                var fromJoin = @" FROM PurchaseInvoice pi
                                   LEFT JOIN Supplier s ON s.Id = pi.SupplierId AND s.IsDeleted = 0
                                   LEFT JOIN ProcurementMaterials pm ON pm.PurchaseInvoiceId = pi.Id AND pm.IsDel = 0";

                // 统计与数据都以“明细行为粒度”，因此要求 pm 明细存在
                whereParts.Add("pm.PurchaseInvoiceMaterialsId IS NOT NULL");

                var whereSql = whereParts.Count > 0 ? (" WHERE " + string.Join(" AND ", whereParts)) : string.Empty;

                // 1) Count total rows (each material line is one row)
                var countSql = "SELECT COUNT(1)" + fromJoin + whereSql;
                var total = _invoiceRepository.Query<int>(countSql, param).FirstOrDefault();
                res.TotalCount = total;

                if (total == 0)
                {
                    res.Code = APIEnums.Success;
                    res.PageDatas = new List<PurchaseInvoiceDetailRowDto>();
                    res.Msg = "获取采购发票明细成功";
                    return Task.FromResult(res);
                }

                // 2) Paged data
                var offset = (request.PageIndex - 1) * request.PageSize;
                if (offset < 0) offset = 0;
                param.Add("Offset", offset);
                param.Add("PageSize", request.PageSize);

                var dataSql = @"SELECT 
                                    pi.Id AS InvoiceId,
                                    pi.DocumentCode,
                                    pi.InvoiceDate,
                                    pi.DocumentDate,
                                    pi.BusinessType,
                                    pi.DocumentStatus,
                                    pi.SupplierId,
                                    s.Supplier_Name AS SupplierName,
                                    pi.InvoiceNumber,
                                    pi.TaxNumber,
                                    pi.InvoiceType,
                                    pm.PurchaseInvoiceMaterialsId,
                                    pm.MaterialCode,
                                    pm.MaterialName,
                                    pm.ModelSpecifications,
                                    pm.MainMeasurement,
                                    pm.`Number` AS Number,
                                    pm.UnitPrice,
                                    pm.Amount,
                                    pm.TaxRate,
                                    pm.TaxAmount,
                                    pm.PriceTaxTotal,
                                    pm.Warehouse,
                                    pm.PurchaseOrderNumber,
                                    pm.InboundOrderNumber
                                " + fromJoin + whereSql + @" 
                                ORDER BY pi.Id DESC, pm.PurchaseInvoiceMaterialsId ASC
                                LIMIT @Offset, @PageSize";

                var rows = _invoiceRepository.Query<PurchaseInvoiceDetailRowDto>(dataSql, param).ToList();

                res.Code = APIEnums.Success;
                res.PageDatas = rows;
                res.Msg = "获取采购发票明细成功";
            }
            catch (Exception ex)
            {
                res.Code = APIEnums.Error;
                res.Msg = "获取采购发票明细失败";
                _logger.LogError(ex, "获取采购发票明细失败: {Message}", ex.Message);
            }

            return Task.FromResult(res);
        }
    }
}
